package com.hibase.core.page.service.pagemenu.impl;


import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageInfo;
import com.hibase.common.entity.user.LoginType;
import com.hibase.common.exception.HibaseAssert;
import com.hibase.common.util.ArrayUtils;
import com.hibase.core.mybatis.service.BaseServiceImpl;
import com.hibase.core.mybatis.util.GenerateIdHelper;
import com.hibase.core.page.entity.pagemenu.PageMenu;
import com.hibase.core.page.entity.pagemenu.vo.PageMenuSearchVO;
import com.hibase.core.page.mapper.pagemenu.PageMenuMapper;
import com.hibase.core.page.service.pagemenu.PageMenuService;
import com.hibase.core.page.utils.FileUtils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.extern.log4j.Log4j2;


/**
 * <p>
 * 页面菜单配置表 服务实现类
 * </p>
 *
 * @author junk
 * @since 2021-03-31
 */
@Log4j2
@Service
public class PageMenuServiceImpl extends BaseServiceImpl<PageMenuMapper, PageMenu> implements PageMenuService {

    @Autowired
    private PageMenuMapper pageMenuMapper;
    
    @Autowired
    ResourceLoader resourceLoader;
    
    private static BigDecimal level3 = new BigDecimal(3);
    private static BigDecimal level4 = new BigDecimal(4);

    /**
     * 查询页面菜单配置表列表
     */
    @Override
    public PageInfo<PageMenu> selectPageMenuList(PageMenuSearchVO searchVO) {

        return super.page(searchVO, new QueryWrapper<PageMenu>());
    }

    /**
     * 改变页面菜单配置表记录
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void savePageMenu(PageMenu entity) {

        super.store(entity);
    }

    /**
     * 查询页面菜单配置表详情
     */
    @Override
    public PageMenu viewPageMenu(String id) {

        PageMenu entity = super.getById(id, true);

        return entity;
    }

    /**
     * 删除页面菜单配置表记录
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deletePageMenu(String id) {

        super.deleteBy(id);
    }


    /**
     * 导出页面菜单配置表记录
     */
    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public void exportPageMenu(PageMenuSearchVO searchVO, HttpServletResponse response) {

//        StringBuilder fileName = new StringBuilder();
//        fileName.append("export-");
//        fileName.append("PageMenu");
//        fileName.append(DateUtil.today());
//        Sheet sheet = null;
//        sheet = new Sheet(1, 1, PageMenuExportVO.class, fileName.toString(), null);
//        //todo
//        AttachmentUtils.exportExcelFile(response, sheet, null, fileName.toString());
    }

    /**
     * (non-Javadoc)
     * <p>Title: syncPageConfigToPageMenu</p>
     * <p>Description: 同步resources pageConfig到pageMenu表中</p>
     *
     * @author TimBrian
     * @see com.hibase.core.page.service.pagemenu.PageMenuService#syncPageConfigToPageMenu()
     * @since 2021年11月10日 下午4:44:15
     */
    @Override
	public void syncPageConfigToPageMenu(LoginType loginType) {

//    	if (loginType.getLoginType().equals(LoginTypeContstants.WMS)) {
//			
//		}
		Resource[] resources = null;
		File file = null;
		try {
			resources = new PathMatchingResourcePatternResolver().getResources("classpath:/pageConfig/" + loginType.getLoginType() + "/*/*");
			HibaseAssert.isFalse(ObjectUtil.isEmpty(resources), "{}目录下是空的", "pageConfig/" + loginType.getLoginType());

			String filePath = null;
			String[] split = null;

			// 需要操作的对象集合
			List<PageMenu> insertList = new ArrayList<PageMenu>();
			//需要删除的目录
			Set<String> deleteIdSet = new HashSet<String>();
			Set<String> allWmsMenuSet = new HashSet<>();
			PageMenu isnertPageMenu = null;

			Map<String, PageMenu> mindPageMenu = new HashMap<String, PageMenu>();

			// 查询数据库中loginType.getLoginType()数据，如果是空则全都同步到表中
			PageMenu selectLevel1 = pageMenuMapper.selectOne(Wrappers.<PageMenu>lambdaQuery().eq(PageMenu::getMenuName, loginType.getLoginType()));

			if (ObjectUtil.isEmpty(selectLevel1)) {
				// 为空
				// step1 获取1级菜单，固定为pageConfig, TODO 写死了
//            	PageMenu selectLevelOne = pageMenuMapper.selectOne(Wrappers.<PageMenu>lambdaQuery().eq(PageMenu :: getMenuName, "pageConfig"));
				// 创建2级目录
				selectLevel1 = new PageMenu();
				selectLevel1.setId(GenerateIdHelper.idGenerate());
				selectLevel1.setLevel(new BigDecimal(2));
				selectLevel1.setParentId("1");
				selectLevel1.setAllParentIds("1");
				selectLevel1.setMenuName(loginType.getLoginType());
				insertList.add(selectLevel1);
				mindPageMenu.put(loginType.getLoginType(), selectLevel1);

			}

			// 不为空则匹配
			List<PageMenu> pageMenuList = pageMenuMapper
					.selectList(Wrappers.<PageMenu>lambdaQuery().like(PageMenu::getAllParentIds, selectLevel1.getId())
							.select(PageMenu::getId, PageMenu::getMenuName, PageMenu::getParentId,
									PageMenu::getAllParentIds, PageMenu::getLevel, PageMenu::getChildQty));

			// 根据级别分类
			Map<BigDecimal, List<PageMenu>> pageMenuLevelMap = pageMenuList.stream().collect(Collectors.groupingBy(PageMenu::getLevel));
			if (pageMenuList != null && pageMenuList.size() > 0) {
				for (PageMenu pageMenu : pageMenuList) {
					mindPageMenu.put(pageMenu.getMenuName(), pageMenu);
				}
			}
			
			for (int i = 0; i < resources.length; i++) {
				file = resources[i].getFile();
				boolean directory = file.isFile();
				filePath = file.getPath();
				if (directory) {
					filePath = filePath.substring(filePath.indexOf("pageConfig\\" + loginType.getLoginType()),
							filePath.lastIndexOf("\\"));
				} else {
					filePath = filePath.substring(filePath.indexOf("pageConfig\\" + loginType.getLoginType()) + 12
							+ loginType.getLoginType().length());// .replace("\\", ",");
				}
				split = filePath.replace(File.separator, ",").split(",");
				if (split.length == 0) {
					continue;
				}
				if (CollUtil.isEmpty(pageMenuList)) {
					//pageMenuList为空-3级目录都是空的 直接创建3级目录
					for (int j = 0; j < split.length; j++) {
						if (j == 0 && !mindPageMenu.containsKey(split[j])) {
							isnertPageMenu = extracted(split, selectLevel1, j, 3, mindPageMenu);
							insertList.add(isnertPageMenu);
							mindPageMenu.put(split[j], isnertPageMenu);
						} else if (j == 1) {
							isnertPageMenu = extracted(split, selectLevel1, j, 4, mindPageMenu);
							insertList.add(isnertPageMenu);
							mindPageMenu.put(split[j], isnertPageMenu);
						}
					}
				} else {
					for (int j = 0; j < split.length; j++) {
						if (j == 0 && !pageMenuLevelMap.get(level3).contains((Object) split[j]) && !mindPageMenu.containsKey(split[j])) {
							isnertPageMenu = extracted(split, selectLevel1, j, 3, mindPageMenu);
							insertList.add(isnertPageMenu);
							mindPageMenu.put(split[j], isnertPageMenu);
						} else if (j == 1 && !pageMenuLevelMap.get(level4).contains((Object) split[j]) && !mindPageMenu.containsKey(split[j])) {
							isnertPageMenu = extracted(split, selectLevel1, j, 4, mindPageMenu);
							insertList.add(isnertPageMenu);
							mindPageMenu.put(split[j], isnertPageMenu);
						}
						allWmsMenuSet.add(split[j]);
					}
				}
			}
			if (allWmsMenuSet != null && allWmsMenuSet.size() > 0) {
				//判断需要删除的目录
				extracted(deleteIdSet, 3 ,allWmsMenuSet, pageMenuLevelMap);
				extracted(deleteIdSet, 4 ,allWmsMenuSet, pageMenuLevelMap);
			}
			// 添加数据
			this.saveBatch(insertList);
			// 删除数据
			deleteBy(deleteIdSet);
		} catch (IOException e) {
			log.error(e.getMessage());
			if (e.getMessage().equals("class path resource [pageConfig/] cannot be resolved to URL because it does not exist")) {
				file = new File("pageConfig");
				file.mkdirs();
			}
		}

	}

    /**
     * @Title: PageMenuServiceImpl
     * @Description: 删除ID
     * @author TimBrian
     * @since 2021年11月18日 下午1:14:46
     * @param deleteIdSet
     * @param level
     * @param allWmsMenuSet
     * @param pageMenuLevelMap
     */
	private void extracted(Set<String> deleteIdSet, Integer level, Set<String> allWmsMenuSet, Map<BigDecimal, List<PageMenu>> pageMenuLevelMap) {
		for (PageMenu pageMenu : pageMenuLevelMap.get(new BigDecimal(level))) {
			if (!allWmsMenuSet.contains(pageMenu.getMenuName())) {
				deleteIdSet.add(pageMenu.getId());
			}
		}
	}

    /**
     * @Title: PageMenuServiceImpl
     * @Description: TODO
     * @author TimBrian
     * @since 2021年11月18日 上午9:52:28
     * @param split
     * @param selectLevel1
     * @param j
     * @param level
     * @param mindPageMenu
     * @return
     */
	private PageMenu extracted(String[] split, PageMenu selectLevel1, int j, Integer level, Map<String, PageMenu> mindPageMenu) {
		PageMenu isnertPageMenu = new PageMenu();
		isnertPageMenu.setId(GenerateIdHelper.idGenerate());
		isnertPageMenu.setLevel(new BigDecimal(level));
		if (level == 4) {
			isnertPageMenu.setParentId(mindPageMenu.get(split[j - 1]).getId());
			isnertPageMenu.setAllParentIds(mindPageMenu.get(split[j - 1]).getAllParentIds() +"/"+ isnertPageMenu.getParentId() );
		}else {
			isnertPageMenu.setParentId(selectLevel1.getId());
			isnertPageMenu.setAllParentIds(selectLevel1.getParentId() + "/" + selectLevel1.getId());
		}
		isnertPageMenu.setMenuName(split[j]);
		return isnertPageMenu;
	}

    /**
     * (non-Javadoc)
     * <p>Title: syncPageMenuToPageConfig</p>
     * <p>Description: 同步pageMenu表到resources pageConfig中</p>
     *
     * @author TimBrian
     * @see com.hibase.core.page.service.pagemenu.PageMenuService#syncPageMenuToPageConfig()
     * @since 2021年11月10日 下午4:54:09
     */
    @Override
    public void syncPageMenuToPageConfig(LoginType loginType) {
    	Resource[] resources = null;
		File file = null;
		try {
			resources = new PathMatchingResourcePatternResolver().getResources("classpath:/pageConfig/" + loginType.getLoginType());
			HibaseAssert.isFalse(ObjectUtil.isEmpty(resources), "{}目录下是空的", "pageConfig/" + loginType.getLoginType());
			
			// 查询2级目录列表
			PageMenu selectLevel2 = pageMenuMapper.selectOne(Wrappers.<PageMenu>lambdaQuery().eq(PageMenu::getMenuName, loginType.getLoginType()));

			if (ObjectUtil.isEmpty(selectLevel2)) {
				// 为空 删除
				for (Resource resource : resources) {
					FileUtils.fileDelete(resource.getFile());
				}
			}
			// 查询 loginType.getLoginType() 下的所有子菜单
			List<PageMenu> pageMenuList = pageMenuMapper.selectList(Wrappers.<PageMenu>lambdaQuery().like(PageMenu::getAllParentIds, selectLevel2.getId()));
//			// 根据级别分类
			Map<BigDecimal, List<PageMenu>> pageMenuLevelMap = pageMenuList.stream().collect(Collectors.groupingBy(PageMenu::getLevel));
			
			Set<String> menuNameSet3 = new HashSet<>(), menuNameSet4 = new HashSet<>();
			Map<String, String> mindPageMenu = new HashMap<String, String>();
			file = resources[0].getFile();
			//3级目录
			File[] listFiles = file.listFiles();
			for (File fileLevel3 : listFiles) {
				String filePath;
				filePath = fileLevel3.getPath();
				filePath = filePath.substring(filePath.lastIndexOf(File.separator) + 1);
				extracted(menuNameSet3, fileLevel3, mindPageMenu);
				//4级目录
				File[] listFiles2 = fileLevel3.listFiles();
				if (listFiles2 == null) {
					continue;
				}
				for (File fileLevel4 : listFiles2) {
					extracted(menuNameSet4, fileLevel4, mindPageMenu);
				}
			}
			//求level3的差集
			Object[] collect3 = pageMenuLevelMap.get(level3).stream().map(e -> e.getMenuName()).toArray(Object[] :: new);
			//求level4的差集
			Object[] collect4 = pageMenuLevelMap.get(level4).stream().map(e -> e.getMenuName()).toArray(Object[] :: new);
			//level3需要删除的数据
			Object[] deleteLevel3 = ArrayUtils.differenceSet(menuNameSet3.toArray(), collect3);
			//level4需要删除的数据
			Object[] deleteLevel4 = ArrayUtils.differenceSet(menuNameSet4.toArray(), collect4);
			//level3需要创建的数据
			Object[] careteLevel3 = ArrayUtils.differenceSet(collect3, menuNameSet3.toArray());
			//level4需要创建的数据
			Object[] careteLevel4 = ArrayUtils.differenceSet(collect4, menuNameSet4.toArray());
			File delFile = null;
			
			for (Object child : deleteLevel3) {
				delFile = new File(file, child.toString());
				boolean fileDelete = FileUtils.fileDelete(delFile);
				log.debug(fileDelete);
			}
			for (Object child : deleteLevel4) {
				delFile = new File(mindPageMenu.get(child));
				boolean fileDelete = FileUtils.fileDelete(delFile);
				log.debug(fileDelete);
			}
			for (Object child : careteLevel3) {
				File dir = new File(file, child.toString());
				if (!dir.exists()) {
					dir.mkdir();
				}
			}
			
			for (Object child : careteLevel4) {
				String parentId = null, menuName = null;
				for (PageMenu pageMenu : pageMenuLevelMap.get(level4)) {
					if (pageMenu.getMenuName().equals(child)) {
						parentId = pageMenu.getParentId();
						break;
					}
				}
				for (PageMenu pageMenu : pageMenuLevelMap.get(level3)) {
					if (pageMenu.getId().equals(parentId)) {
						menuName = pageMenu.getMenuName();
						break;
					}
				}
				File dir = new File(file, menuName + File.separator + child);
				if (!dir.exists()) {
					dir.mkdir();
				}
			}
			
		} catch (IOException e) {
			log.error(e.getMessage());
			if (e.getMessage().equals("class path resource [pageConfig/] cannot be resolved to URL because it does not exist")) {
				file = new File("pageConfig");
				file.mkdirs();
			}
		}

    }

	private void extracted(Set<String> menuNameSet, File file, Map<String, String> mindPageMenu) {
		String filePath = file.getPath();
		filePath = filePath.substring(filePath.lastIndexOf(File.separator) + 1);
		menuNameSet.add(filePath);
		mindPageMenu.put(filePath, file.getPath());
	}
}